/*
 * ServerConnection.java
 *
 * Created on 29 de Julho de 2007, 16:38
 */

package org.gpp.proj1.ui.gui.lobby;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.Properties;

import javax.swing.JOptionPane;
import javax.swing.ListSelectionModel;
import javax.swing.table.DefaultTableModel;

import org.gpp.proj1.communication.CommunicationException;
import org.gpp.proj1.communication.listener.ConnectionAttemptListener;
import org.gpp.proj1.ui.gui.SRGGUIView;

/**
 *
 * @author  Gustavo
 */
public class SCRServerConnection extends javax.swing.JFrame implements ServerCreationHandler, ConnectionAttemptListener {
    
    /**
     *
     */
    private static final long serialVersionUID = -8752100809254649278L;
    
    private static final String KNOWN_SERVERS_FILE = "./res/config/knownServers";
    private static final String NAME_SUFFIX = "nm";
    private static final String ADDRESS_SUFFIX = "ad";
    
    private Properties servers;
    private boolean connecting;

	private final SRGGUIView view;
    
    /** Creates new form ServerConnection */
    public SCRServerConnection(SRGGUIView view) {
        this.view = view;
		this.servers = new Properties();
        try {
            this.servers.load( new FileInputStream( KNOWN_SERVERS_FILE ) );
        } catch (Exception ex) {
            // No problem, a fresh file will be created as necessary
        }
        
        this.connecting = false;
        initComponents();
        this.setLocationRelativeTo(null);
    }
    
    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    // <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
    private void initComponents() {
        instructionLabel = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        serverTable = new javax.swing.JTable();
        newButton = new javax.swing.JButton();
        removeButton = new javax.swing.JButton();
        backButton = new javax.swing.JButton();
        connectButton = new javax.swing.JButton();
        jPanel1 = new javax.swing.JPanel();
        connectionProgressBar = new javax.swing.JProgressBar();
        errorMessageLabel = new javax.swing.JLabel();
        localPortLabel = new javax.swing.JLabel();
        localPortTextField = new javax.swing.JTextField();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("SomeRobotGame");
        setResizable(false);
        instructionLabel.setText("Choose a server to connect to");

        serverTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Name", "Address"
            }
        ) {
            Class[] types = new Class [] {
                java.lang.String.class, java.lang.String.class
            };
            boolean[] canEdit = new boolean [] {
                false, false
            };

            public Class getColumnClass(int columnIndex) {
                return types [columnIndex];
            }

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        serverTable.setAutoResizeMode(javax.swing.JTable.AUTO_RESIZE_ALL_COLUMNS);
        serverTable.setShowVerticalLines(false);
        serverTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        serverTable.getSelectionModel().addListSelectionListener(new javax.swing.event.ListSelectionListener() {
            public void valueChanged(javax.swing.event.ListSelectionEvent evt) {
                serverTableValueChanged(evt);
            }
        });
        this.fillServerTable();
        jScrollPane1.setViewportView(serverTable);

        newButton.setText("New");
        newButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                newButtonActionPerformed(evt);
            }
        });

        removeButton.setText("Remove");
        removeButton.setEnabled(false);
        removeButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeButtonActionPerformed(evt);
            }
        });

        backButton.setText("<< Back");
        backButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                backButtonActionPerformed(evt);
            }
        });

        connectButton.setText("Connect");
        connectButton.setEnabled(false);
        connectButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                connectButtonActionPerformed(evt);
            }
        });

        errorMessageLabel.setText(" ");

        org.jdesktop.layout.GroupLayout jPanel1Layout = new org.jdesktop.layout.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(org.jdesktop.layout.GroupLayout.TRAILING, jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, errorMessageLabel, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE)
                    .add(org.jdesktop.layout.GroupLayout.LEADING, connectionProgressBar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 308, Short.MAX_VALUE))
                .addContainerGap())
        );
        jPanel1Layout.setVerticalGroup(
            jPanel1Layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(jPanel1Layout.createSequentialGroup()
                .addContainerGap()
                .add(errorMessageLabel)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(connectionProgressBar, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        localPortLabel.setText("Local port:");

        localPortTextField.setHorizontalAlignment(javax.swing.JTextField.RIGHT);
        localPortTextField.setText("27015");
        localPortTextField.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                localPortTextFieldFocusGained(evt);
            }
        });

        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                    .add(instructionLabel)
                    .add(jScrollPane1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE)
                    .add(layout.createSequentialGroup()
                        .add(backButton)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 182, Short.MAX_VALUE)
                        .add(connectButton))
                    .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
                        .add(newButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 76, Short.MAX_VALUE)
                        .add(175, 175, 175)
                        .add(removeButton, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 77, Short.MAX_VALUE))
                    .add(jPanel1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .add(layout.createSequentialGroup()
                        .add(localPortLabel)
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                        .add(localPortTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 85, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)))
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
            .add(layout.createSequentialGroup()
                .addContainerGap()
                .add(instructionLabel)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(jScrollPane1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, 138, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(newButton)
                    .add(removeButton))
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED, 21, Short.MAX_VALUE)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(localPortLabel)
                    .add(localPortTextField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
                .add(17, 17, 17)
                .add(jPanel1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                    .add(backButton)
                    .add(connectButton))
                .addContainerGap())
        );
        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void localPortTextFieldFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_localPortTextFieldFocusGained
        this.localPortTextField.selectAll();
    }//GEN-LAST:event_localPortTextFieldFocusGained

    private void connectButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_connectButtonActionPerformed
        // connect
        if (!this.connecting) {

            this.connectButton.setEnabled(false);
            
            this.backButton.setEnabled(false);
            this.newButton.setEnabled(false);
            this.removeButton.setEnabled(false);
            this.serverTable.setEnabled(false);
            this.connectButton.setText("Cancel");
            this.connectionProgressBar.setIndeterminate(true);
            this.errorMessageLabel.setText("Connecting...");

            int index = this.serverTable.getSelectedRow();

            try {
				view.getController().connectToServer( this, (String)this.serverTable.getValueAt(index, 1), this.getLocalPort() );
			} catch (CommunicationException e) {
				JOptionPane.showMessageDialog(this, "Could not connect to server", "Error", JOptionPane.ERROR_MESSAGE);
				this.connectionAttemptFailed( e.getMessage() );
				return;
			}
            
            this.connecting = true;
            this.connectButton.setEnabled(true);
        }
        // cancel
        else {
            
            this.connectButton.setEnabled(false);
            
            this.backButton.setEnabled(true);
            this.newButton.setEnabled(true);
            this.removeButton.setEnabled(true);
            this.serverTable.setEnabled(true);
            this.connectButton.setText("Connect");
            this.connectionProgressBar.setIndeterminate(false);
            this.errorMessageLabel.setText("Canceled by user.");
            
//            this.client.stopConnectionAttempt();
//            this.client.setConnectionAttemptListener(null);
            
            this.connecting = false;
            this.connectButton.setEnabled(true);
        }
    }//GEN-LAST:event_connectButtonActionPerformed

    private void removeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeButtonActionPerformed
        if (this.serverTable.getSelectedRow() != -1) {
            
            ((DefaultTableModel)this.serverTable.getModel()).removeRow( this.serverTable.getSelectedRow() );
            
            this.servers.clear();
            for (int i = 0; i < this.serverTable.getRowCount(); i++) {
                this.servers.put( (i+1) + "." + NAME_SUFFIX, this.serverTable.getValueAt( i, 0 ) );
                this.servers.put( (i+1) + "." + ADDRESS_SUFFIX, this.serverTable.getValueAt( i, 1 ) );
            }
            
            try {
                this.servers.store( new FileOutputStream( new File( KNOWN_SERVERS_FILE ) ), null );
            }
            catch (Exception e) {
                JOptionPane.showMessageDialog(this, "Problem saving server list.", "Error", JOptionPane.ERROR);
            }
            
        }
    }//GEN-LAST:event_removeButtonActionPerformed

    private void newButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_newButtonActionPerformed
        SCRAddServerDialog asd = new SCRAddServerDialog(this, true, this);
        asd.setVisible(true);                
    }//GEN-LAST:event_newButtonActionPerformed

    private void backButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_backButtonActionPerformed
        SCRClientServer cs = new SCRClientServer( this.view );
        cs.setLocationRelativeTo(null);
        cs.setVisible(true);
        this.dispose();
    }//GEN-LAST:event_backButtonActionPerformed
    
    private void serverTableValueChanged(javax.swing.event.ListSelectionEvent evt) {                                    
        if ( this.serverTable.getSelectedRow() == -1) {
            this.removeButton.setEnabled(false);
            this.connectButton.setEnabled(false);
        }
        else {
            this.removeButton.setEnabled(true);
            this.connectButton.setEnabled(true);
        }
    }

    public void createServer(String name, String address) {
        name = name.trim();
        address = address.trim();
        
        ((DefaultTableModel)this.serverTable.getModel()).addRow( new String[]{name, address} );
        
        int next = (this.servers.size() / 2) + 1;
        
        this.servers.put(next + "." + NAME_SUFFIX, name);
        this.servers.put(next + "." + ADDRESS_SUFFIX, address);
        
        try {
            this.servers.store( new FileOutputStream( new File( KNOWN_SERVERS_FILE ) ), null );
        }
        catch (Exception e) {
            JOptionPane.showMessageDialog(this, "Problem saving server list.", "Error", JOptionPane.ERROR);
        }
    }
    
    private void fillServerTable() {
        for (int i = 1; i <= this.servers.size() / 2; i++) {
            ((DefaultTableModel)this.serverTable.getModel()).addRow( new String[]{ this.servers.getProperty(i + "." + NAME_SUFFIX), this.servers.getProperty(i + "." + ADDRESS_SUFFIX)} );
        }
    }

    public void connectionAttemptSucceeded() {
        
        this.connectButton.setEnabled(false);
        this.errorMessageLabel.setText("Connection successful.");

        try {
            Thread.sleep(1000);
        } catch (InterruptedException ex) {}
        
        SCRLobby lobby = new SCRLobby( this.view, false );
        lobby.setVisible(true);
        this.dispose();
    }

    public void connectionAttemptFailed( String errorMessage ) {
        
        this.connectButton.setEnabled(false);
        
        this.backButton.setEnabled(true);
        this.newButton.setEnabled(true);
        this.removeButton.setEnabled(true);
        this.serverTable.setEnabled(true);
        this.connectButton.setText("Connect");
        this.connectionProgressBar.setIndeterminate(false);
        this.errorMessageLabel.setText( errorMessage );
        
        this.connecting = false;
        this.connectButton.setEnabled(true);
    }

    private int getLocalPort() {
        try {
            return Integer.parseInt( this.localPortTextField.getText().trim() );
        }
        catch (NumberFormatException ex) {
            return -1;
        }
    }
    
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton backButton;
    private javax.swing.JButton connectButton;
    private javax.swing.JProgressBar connectionProgressBar;
    private javax.swing.JLabel errorMessageLabel;
    private javax.swing.JLabel instructionLabel;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JLabel localPortLabel;
    private javax.swing.JTextField localPortTextField;
    private javax.swing.JButton newButton;
    private javax.swing.JButton removeButton;
    private javax.swing.JTable serverTable;
    // End of variables declaration//GEN-END:variables
    
}
